﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using SGLisp;
using System.IO;
public class GameTrigger 
{
    public  List<SGTrigger> Triggers = new List<SGTrigger>();
    
    public Dictionary<string, List<SGTrigger>> Events = new Dictionary<string, List<SGTrigger>>();
     
    public SGLisp.Context ClojureContext;

   
    public void Init() 
    {
        ClojureContext = RT.MainContext;
        ActionFuncDefine.Define(ClojureContext);
        DefineTriggerClojureFunc();
    }
    public void Load(string configName) 
    {
        ASTTree triggerAstTree = RT.LoadASTTree(configName);
        RT.EvaluateTree(triggerAstTree);
    }

    public void AddTrigger(SGTrigger trigger) 
    {
        this.Triggers.Add(trigger);
        for (int i = 0; i < trigger.TriggerEvents.Count;i++ ) 
        {
           TriggerEvent  curEvent = trigger.TriggerEvents[i];
           if (!this.Events.ContainsKey(curEvent.EventName))
           {
               this.Events[curEvent.EventName] = new List<SGTrigger>();
           }
           this.Events[curEvent.EventName].Add(trigger);
        }
    }

    public void CallEvent(string eventName,Hashtable argDic = null)
    { 
        if (this.Events.ContainsKey(eventName)) 
        {
            List<SGTrigger> Triggers = this.Events[eventName];
            for (int i = 0; i < Triggers.Count; i++) 
            {
                Triggers[i].OnTrigger(argDic); 
            }
        }
    }

    void DefineTriggerClojureFunc() 
    {
        ClojureContext.Define("def-trigger",new FunctionNode(_def_Trigger));
        ClojureContext.Define("def-event", new FunctionNode(_def_event));
        ClojureContext.Define("actions", new FunctionNode(_actions));
    }

    public string GetTriggerConfigPath()
    {
          return "../Public/Configs/GameCore/GameTrigger.clj";
    }
    ASTNode _def_Trigger(List<ASTNode> args,Context context)
    {
       SGTrigger newTrigger = new SGTrigger(context);
       VectorNode triggerArg = (VectorNode)args[0];
       for (int i=0;i<triggerArg.nodes.Length;i+=2)
       {
          SymbolNode symNode = (SymbolNode)triggerArg.nodes[i];
          newTrigger.ClojureContext.Define(symNode.Val,RT.Evaluate(triggerArg.nodes[i+1],context));
       }

       args.RemoveAt(0);
       MapNode triggerDic = (MapNode)CoreFunction.HashMap(args,context);
       triggerDic = (MapNode)RT.Evaluate(triggerDic,context);
       Hashtable triggerTable = (Hashtable)RT.EvalNode(triggerDic,context);
       //描述
       newTrigger.Desc = (string)triggerTable[":desc"];
       //事件
       object[] EventNodes = (object[])triggerTable[":event"];
       for (int i=0;i< EventNodes.Length;i++)
       {
            TriggerEvent triggerEvent = (TriggerEvent)EventNodes[i];
            newTrigger.AddEvent(triggerEvent);
       }
       //条件
       newTrigger.ConditionNode = (FunctionNode)triggerTable[":condition"];
       //动作
       newTrigger.ActionNodes = (List<BaseAction>)triggerTable[":actions"];

        AddTrigger(newTrigger);
        return new ObjectNode(newTrigger);
    }

    static ASTNode _def_event(List<ASTNode> args, Context context) 
    {
        string eventName = ((StringNode)args[0]).Val;
        TriggerEvent newEvent  =(TriggerEvent) System.Activator.CreateInstance(System.Type.GetType(eventName + "Event"));
        newEvent.OnLoad(args);
        return new ObjectNode(newEvent);
    }

    public ASTNode _actions(List<ASTNode> args,Context context) 
    {
        List<BaseAction> actions = new List<BaseAction>();
        for (int i = 0; i < args.Count; i++) 
        {
             ListNode node = ((ListNode)args[i]);
             ASTNode actionNode = _action(node, context);
             if (node != null) 
             {
                BaseAction action = (BaseAction)((ObjectNode)actionNode).Val;

                actions.Add(action);
             }
        }
        return new ObjectNode(actions);
    }



    public ASTNode _action(ListNode lstNode, Context context) 
    {
        SymbolNode actionNameNode = ((SymbolNode)lstNode.nodes.First.Value);
        //如果从脚本作用域中找到了这个动作那么他就是一个非阻塞动作
        ASTNode actionFuncNode = context.Find(actionNameNode.Val);
        if (actionFuncNode != null)
        {
            NonBlockAction curNewAction = new NonBlockAction(lstNode);
            return new ObjectNode(curNewAction);
        }
        //如果没找到他就是一个阻塞动作
        else
        {
            //利用反射创建这个动作类
            BlockAction blockAction = (BlockAction)System.Activator.CreateInstance(System.Type.GetType(actionNameNode.Val+"Action"));
            blockAction.Typ = BaseAction.ActionType.Block;
            blockAction.ActionNode = lstNode;
            blockAction.OnLoad(new List<ASTNode>(lstNode.nodes));
            if (blockAction == null)
            {
                Debug.LogError("使用了不存在的动作节点");
            }
            else
            {
                return new ObjectNode(blockAction);
            }
        }
        return new NilNode(); 
    }

    public void Update() 
    {
        CallEvent("Periodic");
        for (int i = 0; i < this.Triggers.Count; i++)
        {
            this.Triggers[i].Update();
        }
    }

    public void Destory() 
    {
    
    }
   
}
 